#!/usr/bin/python
# -*- coding: utf-8 -*-
# File: provider.py
# Author: Tomás Vírseda
# License: GPL v3
# Description:  arguments are parsed by this provider and try to guess what is it.


import fnmatch
import os
import re
from os.path import abspath, isdir, basename
import Queue
import sys
if sys.version_info < (2, 4, 0):
    from sets import Set as set
    del sys
import gc
from urlparse import urlparse
from stat import *
import time
from datetime import datetime

import gtk

from rdflib.Graph import Graph
from rdflib import URIRef

from rdflib import Literal
from rdflib import RDF

from xdg import Mime

from vazaarlib.metadata import Metadata
#from vazaarlib.metadata import extract_metadata
from vazaarlib.vresource import VirtualResource
#from vzresource import VazaarResource
from vazaarlib.resource import Resource, Collection
from vazaarlib.constants import RESOURCES_DIR, VAZAAR_USER_RESOURCES_DIR
from vazaarlib.utils import *
from vazaarlib.namespaces import *

class DataProvider:
    id = 0
    text = ""
    fraction = 0.1
    percentaje = "0%"


    def __init__(self, app):
        self.app = app
        self.log = get_logger("Provider") # create logger
        self.running = False # Data Provider status
        self.bag = None
        self.store = Graph()
        self.queue = Queue.Queue(0)
        self.ncol = 0
        self.total = 0
        self.metadata = Metadata(self)

    def guess_type(self, arg):
        try:
            #FIXME: get parsed uri
            inode = os.stat(arg)[ST_INO]
            mode = os.stat(arg)[ST_MODE]
            if S_ISDIR(mode):
                return "dir"
            elif S_ISREG(mode):
                return "regular"
            elif S_ISCHR(mode):
                return "char"
            elif S_ISBLK(mode):
                return "block"
            elif S_ISFIFO(mode):
                return "fifo"
            elif S_ISLNK(mode):
                return "link"
            elif S_ISSOCK(mode):
                return "socket"
        except:
            net = urlparse(arg)
            if net.scheme:
                    return "network"
            else:
                return "string"


    def parse_args(self, thing):
        """
        Analize the input (thing) getting its type and decide:
        - if thing is a path vazaar will walk all the tree from that
        point and will add each file or directory to store (even if they
        are hidden files.
        - In the other hand, if the thing is dir, regular, char, block, fifo, link, socket, network or string(unknow)
        """
        if not thing:
            return None

        self.bag = []
        for path in thing:
            thing_type = self.guess_type(path)
            #self.log.debug("checking %s\nContent:\n%s" % (thing_type, path))
            if thing_type == 'string':
                self.bag.append(path)
            else:
                try:
                    url = os.path.normpath(os.path.dirname(path))
                    mime = Mime.get_type(path)
                    if (mime.subtype == 'directory'):
                        for root, dirs, files in os.walk(path):
                            self.bag.append(root)
                            for selected_dir in dirs:
                                self.bag.append(os.path.join(root, selected_dir))
                            for selected_file in files:
                                self.bag.append(os.path.join(root, selected_file))
                    else:
                        # other things (webpages, notes, events?)
                        self.bag.append(path)

                except Exception, e:
                    msg = "parse_args_error:", e
                    self.log.debug(msg)
                    raise

        #for item in bag:
        #    self.log.debug(item)


    def stop(self):
        self.running = False

    def prepare(self, job=None):
        """
        Parse a bag of things
        """
        self.store = None
        self.store = Graph()
        self.total = 0
        if job:
            self.parse_args(job)

    def attach(self, node):
        if node:
            for s, p, o in node:
                self.store.add((s, p, o))


    def add_resource_to_collection(self, res, thing, col, thing_type):
        if not thing:
            return None

        res.get_metadata(thing, thing_type)
        if res.store:
            #self.log.debug("adding: %s" % thing)
            col.add(res.id)
            for s, p, o in res.store:
                col.store.add((s, p, o))
        del res


    def update_statusbar(self):
        message = "<b>Job[%d]</b>: Resource (<i>%s</i>)" % (self.id, self.text[0:100])
        self.app.set_message(message)
        self.app.set_fraction(self.fraction)
        self.app.set_percentaje(self.percentaje)

    def run(self, id):
        self.running = True # Provider is working
        self.id = id
        self.text = 'Feeding provider. Wait please...'
        self.percentaje = '0%'
        current = 0

        self.total = len(self.bag)

        if (self.total == 0): # no resources provided ??
            self.log.debug("Job[%d]: no resources provided" % id)
            self.gui.actions.update_statusbar("Job[%d]: no resources provided" % id)
            time.sleep(1)
            return None
        elif (self.total == 1):
            # Adding a single resource
            thing = self.bag[0]
            thing_type = self.guess_type(thing)

            vres = VirtualResource() # Create a new Virtual Resource
            vres.set_id()
            #metadata = extract_metadata(vres.id, thing, thing_type)
            metadata = self.metadata.extract(vres.id, thing, thing_type)
            vres.set_metadata(metadata) # Set metadata
            self.app.vstore.add_resource(vres) # Store and cache it

            # create a new file if it is a string-based resource
            if thing_type == 'string':
                # create a new file whose name is its id
                filename = VAZAAR_USER_RESOURCES_DIR + '/' + vres.id[9:]
                f = open(filename, 'w')
                f.write(thing)
                f.close()

            current += 1
            self.text = thing
            self.fraction = 1.0
            self.percentaje = '100%'
            self.update_statusbar()
            self.log.debug("Job[%d]: single resource" % self.id)
            icon = self.app.gui.icons.get_icon_by_name(vres.prop[RDF['type']][0], 128, 128)
            self.app.gui.actions.notify('%s' % vres.prop[NIE['title']][0], "<big>A new resource was added to Vazaar</big>", icon)

            self.set_running(False) # Provider stop working
        else:
            # Adding a collection
            name = self.bag[0]
            if isdir(name):
                name = basename(name)

            now = str(datetime.now())[0:19]
            #now = datetime.datetime.strptime(now, "%Y-%m-%d %H:%M:%S")


            # Create a new Collection
            vcol = VirtualResource()
            vcol.set_id()
            header = []
            header.append((RDF.type, PIMO['Collection']))
            header.append((NIE['title'], Literal(name)))
            header.append((NAO['created'], Literal(str(now))))
            header.append((NAO['lastModified'], Literal(str(now))))
            self.ncol = self.ncol + 1

            for thing in self.bag:
                if self.running:
                    # Create a new Virtual Resource
                    thing_type = self.guess_type(thing)
                    vres = VirtualResource()
                    vres.set_id()
                    #metadata = extract_metadata(vres.id, thing, thing_type)
                    metadata = self.metadata.extract(vres.id, thing, thing_type)
                    vres.set_metadata(metadata)
                    self.app.vstore.add_resource(vres)
                    #add to collection
                    header.append((NIE['hasLogicalPart'], vres.id))

                    # Update stats and GUI
                    current += 1
                    self.fraction = (current*1.0)/(self.total*1.0)
                    percentaje = "%d%%" % (int(self.fraction*100))
                    self.text = thing
                    self.percentaje = percentaje
                    self.update_statusbar()
                else:
                    return
            vcol.set_metadata(header)
            self.app.vstore.add_resource(vcol)
            self.log.debug("Job[%d]: collection" % id)
            icon = self.app.gui.icons.get_icon_by_name('Collection-add.svg', 128, 128)
            self.app.gui.actions.notify('%s' % name, "<big>A new collection was added to Vazaar</big>", icon)

            self.running = False # Provider stop working

    def test(self):
        pass

    def get_message(self):
        return self.message

    def set_running(self, running):
        self.running = running

